<html>

<head>
  <meta charset="utf-8">
  <title>P2P Demo</title>
  <style>
      body {
          overflow: hidden;
          margin: 0px;
          padding: 0px;
      }

      #local_view {
          width: 100%;
          height: 100%;
      }

      #remote_view {
          width: 9%;
          height: 16%;
          position: absolute;
          top: 10%;
          right: 10%;
      }

      #left {
          width: 10%;
          height: 5%;
          position: absolute;
          left: 10%;
          top: 10%;
      }

      #p_websocket_state,
      #input_server_url,
      .my_button {
          width: 100%;
          height: 100%;
          display: block;
          margin-bottom: 10%;
      }
      .input-item {
          height: 40px;
          margin-bottom: 10px;
      }
  </style>
  <!-- Import style -->
  <link rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css" />
  <!-- Import Vue 3 -->
  <script src="//unpkg.com/vue@3"></script>
  <!-- Import component library -->
  <script src="//unpkg.com/element-plus"></script>
</head>

<body>
<video id="local_view" autoplay controls muted></video>
<video id="remote_view" autoplay controls muted></video>

<div id="left">
  <p id="p_websocket_state">WebSocket 已断开</p>
  <div>本地</div>
  <input class="input-item" id="form" type="text" placeholder="本地房间号" value="1003"></input>
  <div>远程</div>
  <input class="input-item" id="to" type="text" placeholder="其他房间号" value="1001"></input>



  <input id="input_server_url" type="text" placeholder="请输入服务器地址" value="wss://192.168.3.12/wss/websocket"></input>
  <button id="btn_connect" class="my_button" onclick="connect()">连接 WebSocket</button>
  <button id="btn_disconnect" class="my_button" onclick="disconnect()">断开 WebSocket</button>
  <button id="btn_call" class="my_button" onclick="call()">呼叫</button>
  <button id="btn_hang_up" class="my_button" onclick="hangUp()">挂断</button>
</div>
</body>

<script type="text/javascript">

  let localView = document.getElementById("local_view");
  let remoteView = document.getElementById("remote_view");

  const form_input = document.getElementById('form')
  const to_input = document.getElementById('to')


  var localStream;
  var peerConnection = null;

  function createPeerConnection() {
    let rtcPeerConnection = new RTCPeerConnection();
    rtcPeerConnection.oniceconnectionstatechange = function (event) {
      if ("disconnected" == event.target.iceConnectionState) {
        hangUp();
      }
    }
    rtcPeerConnection.onicecandidate = function (event) {
      console.log("onicecandidate--->" + event.candidate);
      let iceCandidate = event.candidate;
      if (iceCandidate == null) {
        return;
      }
      sendIceCandidate(iceCandidate);
    }
    rtcPeerConnection.ontrack = function (event) {
      console.log("remote ontrack--->" + event.streams);
      let streams = event.streams;
      if (streams && streams.length > 0) {
        remoteView.srcObject = streams[0];
      }
    }
    return rtcPeerConnection
  }

  function call() {
    if (peerConnection) {
      hangUp()
    }
    // 创建 PeerConnection
    peerConnection = createPeerConnection();
    // 为 PeerConnection 添加音轨、视轨
    for (let i = 0; localStream != null && i < localStream.getTracks().length; i++) {
      const track = localStream.getTracks()[i];
      peerConnection.addTrack(track, localStream);
    }
    // 通过 PeerConnection 创建 offer，获取 sdp
    peerConnection.createOffer().then(function (sessionDescription) {
      console.log("create offer success.");
      // 将 offer sdp 作为参数 setLocalDescription
      peerConnection.setLocalDescription(sessionDescription).then(() => {
        console.log("set local sdp success.");
        // 发送 offer sdp
        sendOffer(sessionDescription)
      }, (error) => {
        console.log('错误信息', error)
      })
    })
  }

  function hangUp() {
    if (!peerConnection) {
      peerConnection.close();
      peerConnection = null;
    }
    remoteView.removeAttribute('src');
    remoteView.load();
  }

  function sendOffer(offer) {
    var jsonObject = {
      "msgType": "sdp",
      "type": offer.type,
      "sdp": offer.sdp,
      "from": form_input.value.toString(),
      "to": to_input.value.toString(),
    };
    send(JSON.stringify(jsonObject));
  }

  function receivedOffer(offer) {
    try {
      // 创建 PeerConnection
      peerConnection = createPeerConnection();
      // 为 PeerConnection 添加音轨、视轨
      for (let i = 0; localStream != null && i < localStream.getTracks().length; i++) {
        const track = localStream.getTracks()[i];
        peerConnection.addTrack(track, localStream);
      }
      // 将 offer sdp 作为参数 setRemoteDescription
      peerConnection.setRemoteDescription(offer).then(function () {
        console.log("set remote sdp success.");
        // 通过 PeerConnection 创建 answer，获取 sdp
        peerConnection.createAnswer().then(function (sessionDescription) {
          console.log("create answer success.");
          // 将 answer sdp 作为参数 setLocalDescription
          peerConnection.setLocalDescription(sessionDescription).then(function () {
            console.log("set local sdp success.");
            // 发送 answer sdp
            sendAnswer(sessionDescription);
          })
        })
      })
    } catch (error) {
      console.log(error, 77777777)
    }
  }

  function sendAnswer(answer) {
    var jsonObject = {
      "msgType": "sdp",
      "type": answer.type,
      "sdp": answer.sdp,
      "from": form_input.value.toString(),
      "to": to_input.value.toString(),
    };
    send(JSON.stringify(jsonObject));
  }

  function receivedAnswer(answer) {
    // 收到 answer sdp，将 answer sdp 作为参数 setRemoteDescription
    peerConnection.setRemoteDescription(answer).then(function () {
      console.log("set remote sdp success.");
    })
  }

  function sendIceCandidate(iceCandidate) {
    var jsonObject = {
      "msgType": "iceCandidate",
      "iceID": iceCandidate.sdpMid,
      "iceLabel": iceCandidate.sdpMLineIndex,
      "candidate": iceCandidate.candidate,
      "from": form_input.value.toString(),
      "to": to_input.value.toString(),
    };
    send(JSON.stringify(jsonObject));
  }

  function receivedCandidate(iceCandidate) {
    peerConnection.addIceCandidate(iceCandidate);
  }

  navigator.mediaDevices.getUserMedia({audio: true, video: true}).then(function (mediaStream) {
    // 初始化 PeerConnectionFactory
    // 创建 EglBase
    // 创建 PeerConnectionFactory
    // 创建音轨
    // 创建视轨
    localStream = mediaStream;
    // 初始化本地视频渲染控件
    // 初始化远端视频渲染控件
    // 开始本地渲染
    localView.srcObject = mediaStream;
  }).catch(function (error) {
    console.log("error--->" + error);
  })

</script>

<script type="text/javascript">
  var websocket;


  function connect() {
    let inputServerUrl = document.getElementById("input_server_url");
    let pWebsocketState = document.getElementById("p_websocket_state");
    let url = `${inputServerUrl.value}/${form_input.value}`;
    websocket = new WebSocket(url);
    websocket.onopen = function () {
      console.log("onOpen");
      pWebsocketState.innerText = "WebSocket 已连接";
    }
    websocket.onmessage = function (message) {
      console.log("onmessage--->" + message.data);
      let jsonObject = JSON.parse(message.data);
      let msgType = jsonObject["msgType"];
      if ("sdp" == msgType) {
        let type = jsonObject["type"];
        if ("offer" == type) {
          let options = {
            "type": jsonObject["type"],
            "sdp": jsonObject["sdp"]
          }
          let offer = new RTCSessionDescription(options);
          receivedOffer(offer);
        } else if ("answer" == type) {
          let options = {
            "type": jsonObject["type"],
            "sdp": jsonObject["sdp"]
          }
          let answer = new RTCSessionDescription(options);
          receivedAnswer(answer);
        }
      } else if ("iceCandidate" == msgType) {
        let options = {
          "sdpMLineIndex": jsonObject["iceLabel"],
          "sdpMid": jsonObject["iceID"],
          "candidate": jsonObject["candidate"]
        }
        let iceCandidate = new RTCIceCandidate(options);
        receivedCandidate(iceCandidate);
      } else {
        hangUp()
      }
    }
    websocket.onclose = function (error) {
      console.log("onclose--->" + error);
      pWebsocketState.innerText = "WebSocket 已断开";
    }
    websocket.onerror = function (error) {
      console.log("onerror--->" + error);
    }
  }

  function disconnect() {
    websocket.close();
  }

  function send(message) {
    if (!websocket) {
      return;
    }
    websocket.send(message);
  }

</script>

</html>